package com.yeziji.security.common.logger;

import cn.hutool.core.util.StrUtil;
import com.yeziji.utils.ServletUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

/**
 * 读取 httpServletRequestWrapper 请求
 *
 * @author hwy
 * @since 2023/11/12 23:06
 **/
public class LoggerRequestWrapper extends HttpServletRequestWrapper {
    /**
     * 请求体
     */
    private final String body;

    public LoggerRequestWrapper(HttpServletRequest request) {
        super(request);
        this.body = this.getBody(request);
    }

    /**
     * 重写 getReader 方法
     *
     * @return {@link BufferedReader} 获取请求体方法
     * @throws IOException IO 异常
     */
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    /**
     * 重写 getInputStream 方法，让流可重复使用
     *
     * @return {@link ServletInputStream} byteArrayInputStream 读取的流对象
     * @throws IOException IO 异常
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        // 如果 body 为空，就返回原来的流
        if (StrUtil.isBlank(body)) {
            return super.getInputStream();
        }

        // 返回可重复使用流
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read() {
                return byteArrayInputStream.read();
            }

            @Override
            public void close() throws IOException {
                super.close();
                byteArrayInputStream.close();
            }
        };
    }

    /**
     * 获取请求体字符串
     *
     * @return {@link String} 请求体字符串
     */
    public String getBody() {
        return StrUtil.cleanBlank(body);
    }

    /**
     * 解析获取请求体字符串
     *
     * @param request 请求
     * @return 请求体
     */
    private String getBody(HttpServletRequest request) {
        return ServletUtils.getBodyString(request);
    }
}
